<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>动画&反色</title>
  <style>
    html {
      height: 100%;
      cursor: none;

    }

    body {
      background: #eee;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;

      overflow: hidden;
    }

    .content {
      width: 400px;
      background: #42b983;
      color: #fff;
      border: 3px solid #333;
      border-radius: 5px;
      position: relative;
    }

    /* 覆盖content添加反色效果 */
    .content::before {
      content: "";
      position: absolute;
      inset: -10px;
      background: #fff;
      z-index: 1;
      mix-blend-mode: difference;
    }

    #pointer,
    #circle {
      position: absolute;
      top: 0;
      left: 0;
      border-radius: 50%;
      pointer-events: none;
      mix-blend-mode: exclusion;
    }

    #pointer {
      width: 10px;
      height: 10px;
      background-color: #4caf50;
    }

    #circle {
      width: 42px;
      height: 42px;
      background: #fff;
      transition: .15s ease-out;
    }
  </style>
</head>

<body>

  <div class="content">
    个效果，比较核心的一块便是当鼠标 Hover 上去时，整个元素叠加上一层黑色图层，但是呈现了不一样的叠加效果。
    这个了解混合模式（mix-blend-mode）的同学应该一下就能想到。
    在之前，我们也有多篇文章讲解过混合模式，感兴趣的可以随意快速浏览一下，下面是我写过的 15 篇与混合模式相关的合集链接：
  </div>
  <div id="circle"></div>
  <div id="pointer"></div>

</body>

<script>
  const circle = document.getElementById('circle')
  const cursor = document.getElementById('pointer')
  const halfCursorWidth = cursor.offsetWidth / 2;
  const halfCircleWidth2 = circle.offsetWidth / 2;
  const defaultStyle = {
    width: "42px",
    height: "42px",
    borderRadius: '50%',
  }
  let isHovering = false;


  document.body.addEventListener('mousemove', (e) => {
    requestAnimationFrame(() => {
      setPosition(e.clientX, e.clientY);
    });
  })

  window.addEventListener("mouseover", (event) => {
    const target = event.target;
    // 仅仅当鼠标滑动到目标元素
    if (!target.classList.contains("content")) return

    isHovering = true;
    const rect = target.getBoundingClientRect()
    const style = window.getComputedStyle(target);

    circle.style.width = `${rect.width + 20}px`
    circle.style.height = `${rect.height + 20}px`
    circle.style.borderRadius = style.borderRadius
    circle.style.transform = `translate(${rect.left - 10}px, ${rect.top - 10}px)`
  });

  window.addEventListener("mouseout", (event) => {
    const target = event.target;
    if (target.classList.contains("content")) {
      isHovering = false;
      circle.style = defaultStyle
    }
  });


  function setPosition(x, y) {
    cursor.style.transform = `translate(${x - halfCursorWidth}px, ${y - halfCursorWidth}px)`;
    if (isHovering) return
    circle.style.transform = `translate(${x - halfCircleWidth2}px, ${y - halfCircleWidth2
      }px)`;
  }

</script>

</html>